package gpstools;

import gpstools.math.GeoCalculations;
import gpstools.track.TrackPoint;
import gpstools.track.TrackPoint.Builder;

/**
 * @author Marcin Skruch
 */
public class LineSegment {
    private final TrainingPoint start;
    private final TrainingPoint end;

    public LineSegment(Location start, Location end) {
        this(TrackPoint.builder(new Point(start)).build(), TrackPoint.builder(new Point(end)).build());
    }

    public LineSegment(TrainingPoint start, TrainingPoint end) {
        super();
        if (start == null || end == null) {
            throw new IllegalArgumentException("Null arguments not allowed.");
        }
        this.start = start;
        this.end = end;
    }

    public TrainingPoint getStart() {
        return start;
    }

    public TrainingPoint getEnd() {
        return end;
    }
    
    public Location closestLocationTo(Location destination){
        Location location = GeoCalculations.closestSegmentPoint(destination.getLatitude(), destination.getLongitude(),
                start.getLatitude(), start.getLongitude(), end.getLatitude(), end.getLongitude());
        return location;
    }
    
    public double distanceTo(Location destination){
        return Points.distance(closestLocationTo(destination), destination);
    }

    public TrainingPoint closestPointTo(Location destination) {
        Location location = closestLocationTo(destination);
        double distanceFromStart = Points.distance(start, location);
        double distanceTotal = Points.distance(start, end);
        double ratio = distanceFromStart / distanceTotal;

		Double ele = null;
		if (start.getElevation() != null && end.getElevation() != null) {
			ele = start.getElevation()
				+ (end.getElevation() - start.getElevation()) * ratio;
		}
        Builder builder = TrackPoint.builder(new Point(location.getLatitude(), location.getLongitude(), ele));
        /* time */
        if (start.getTime() != null && end.getTime() != null) {
            long time = Math.round(start.getTime() + (end.getTime() - start.getTime()) * ratio);
            builder.time(time);
        }

        if (start.getHeartRate() != null && end.getHeartRate() != null) {
            short hr = (short) Math.round(start.getHeartRate() + (end.getHeartRate() - start.getHeartRate()) * ratio);
            builder.heartRate(hr);
        }
        if (start.getCadence() != null && end.getCadence() != null) {
            short cad = (short) Math.round(start.getCadence() + (end.getCadence() - start.getCadence()) * ratio);
            builder.cadence(cad);
        }

        return builder.build();
    }

}
